// SPDX-License-Identifier: GPL-2.0 or GPL-3.0
// Copyright © 2018-2019 Ariadne Devos
/* sHT -- schedule tasks */

#include "worker.h"

#include <sHT/compiler.h>
#include <sys/epoll.h>
#include <sHT/index.h>
#include <sHT/scheduling.h>
#include <sHT/task.h>
#include <sHT/test.h>

__attribute__((returns_nonnull))
__attribute__((const))
static struct sHT_task *
sHT_task_from_epoll_data(epoll_data_t d)
{
	/* Alternatively, store an offset into worker->tasks.
	   That should speed up worker transmutation up to some degree
	   by being able to hand an epoll set over instead of having
	   to create it all over, or modifying the data value. */

	/* If the pointer is invalid, e.g. due to buggy migration code
	   (forgetting to fix up pointers), an assert would make this
	   crash. Otherwise, a segfault would do that.

	   Both work most of the time, but sometimes they don't, so
	   there is not much of an advantage. So don't check.
	   (The kernel is trusted.) */

	return d.ptr;
}

void
sHT_schedule_events(struct sHT_worker *worker, size_t n)
{
	size_t i;
	sHT_index_iterate(i, n) {
		struct epoll_event e = worker->epoll_events[i];
		struct sHT_task *task = sHT_task_from_epoll_data(e.data);
		task->epollflags |= e.events;
		/* Something can be done, if there is spare memory, even
		   if 'something' is ignoring it. Edge-triggered. */
		sHT_qadd_try(&worker->todo.queue, task);
	}
}
